package com.wxh.restful.common;

import com.wxh.restful.annotations.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * @ClassName: ResponseResultAdvice
 * @Description: 响应结果通知列
 * @Author wxh
 * @Date: 2020/7/17 16:20
 * @Version V1.0.0
 * @Since 1.8
 */
@Slf4j
@ControllerAdvice
public class ResponseResultAdvice implements ResponseBodyAdvice<Object> {
    /*
     * ResponseBodyAdvice, 可以修改返回值直接作为 ResponseBody类型处理器的返回值
     *
     * ControllerAdvice 三种场景
     * 1.全局异常处理
     * 2.全局数据绑定
     * 3.全局数据预处理
     *
     */

    /**
     * 注解属性标记
     */
    public static final String RESPONSE_RESULT_ANNOTATION = "RESPONSE-RESULT-ANNOTATION";

    /**
     *  是否请求包含此注解标记，没有就直接返回，不用重写返回体
     * @param returnType 方法参数对象
     * @param converterType 类类对象
     * @return boolean
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        // 判断请求是否包含此注解标记
        ResponseResult responseResultAnnotation = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANNOTATION);
        return responseResultAnnotation != null;
    }

    @Nullable
    @Override
    public Object beforeBodyWrite(@Nullable Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        log.info(" 进入方法时, 返回体,重写格式, 处理中......");
        // 异常情况处理
        if(body instanceof ErrorResult){
            log.info("返回值异常，做包装，处理中......");
            ErrorResult errorResult = (ErrorResult)body;
            return ResultInfo.failure(errorResult.getCode(), errorResult.getMessage(), errorResult.getErrors());
        }
        return ResultInfo.success(body);
    }
}
